/**
 * Copyright (c) 2011 eelpo.com
 * All rights reserved.
 */
package com.eelpo.cmmp.uac.init;

import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import com.eelpo.cmmp.core.exception.ServiceException;
import com.eelpo.cmmp.uac.dao.vo.Action;
import com.eelpo.cmmp.uac.dao.vo.Entity;
import com.eelpo.cmmp.uac.dao.vo.EntityType;
import com.eelpo.cmmp.uac.dao.vo.Permission;
import com.eelpo.cmmp.uac.dao.vo.enumed.Status;
import com.eelpo.cmmp.uac.services.IActionManageService;
import com.eelpo.cmmp.uac.services.IEntityManageService;
import com.eelpo.cmmp.uac.services.IEntityTypeManageService;
import com.eelpo.cmmp.uac.services.IPermissionManageService;
import com.eelpo.common.util.BlankUtils;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;

/**
 * <pre>
 * 实体初始化
 * </pre>
 * 
 * @author <a href="mailto:Brian@eelpo.com">汪洪州</a>
 * @since 1.0
 */
public class EntityInit implements ApplicationContextAware {

	private static final Logger logger = LoggerFactory.getLogger(EntityInit.class);

	private boolean check;

	public void setCheck(boolean check) {
		this.check = check;
	}

	public boolean isCheck() {
		return check;
	}

	/**
	 * (non-Javadoc)
	 * 
	 * @see org.springframework.context.ApplicationContextAware#setApplicationContext
	 *      (org.springframework.context.ApplicationContext)
	 */

	@Override
	public void setApplicationContext(ApplicationContext context) throws BeansException {
		if (isCheck()) {
			// 初始化实体
			try {
				initEntities(context);
			} catch (IOException e) {
				logger.error("Init entity fail:{}", e.getMessage());
			}
		}
	}

	public void initEntities(ApplicationContext context) throws IOException {

		IEntityManageService entityManageService = (IEntityManageService) context.getBean("entityManageService");
		IActionManageService actionManageService = (IActionManageService) context.getBean("actionManageService");
		IPermissionManageService permissionManageService = (IPermissionManageService) context.getBean("permissionManageService");
		IEntityTypeManageService entityTypeManageService = (IEntityTypeManageService) context.getBean("entityTypeManageService");

		// 获取所有启用的动作
		Map<String, Action> actionMap = new HashMap<String, Action>();

		try {
			List<Action> actions = actionManageService.getEnabledActions();
			for (Action action : actions) {
				actionMap.put(action.getCode().toUpperCase(), action);
			}

		} catch (ServiceException e) {
			logger.warn("get all enabled action fail:{}", e.getMessage());
		}

		try {
			EntityType type = entityTypeManageService.getEntityTypeByCode("MENU");
			Resource[] resources = new PathMatchingResourcePatternResolver().getResources("classpath*:conf/entity-*.properties");
			for (Resource resource : resources) {
				logger.info("Init entity from file:{}", resource.getFilename());
				Properties prop = new Properties();
				prop.load(resource.getInputStream());
				String[] configs = prop.getProperty("Entity").split(",");
				for (String config : configs) {
					recursionInitEntity(config, null, type, actionMap, prop, entityManageService, permissionManageService);
				}
			}
		} catch (ServiceException e) {
			logger.warn("get MENU entity type fail:{}", e.getMessage());
		}
	}

	public void recursionInitEntity(String config, Entity parent, EntityType type, Map<String, Action> actionMap, Properties prop, IEntityManageService entityManageService,
			IPermissionManageService permissionManageService) {

		Entity entity = new Entity();

		entity.setCode(prop.getProperty(config.concat(".code"), config));

		boolean exist = false;

		try {
			exist = entityManageService.checkExist(entity.getCode());
		} catch (Exception e) {
			logger.error(e.getMessage());
		}

		if (exist) {
			try {
				entity = entityManageService.getEntityByCode(entity.getCode());
			} catch (ServiceException e) {
				logger.warn("get exist entity {} fail:{}", entity, e.getMessage());
			}
		} else {
			entity.setParent(parent);
			entity.setType(type);
			entity.setName(prop.getProperty(config.concat(".name"), config));
			entity.setIndex(Integer.parseInt(prop.getProperty(config.concat(".index"))));
			entity.setDescription(prop.getProperty(config.concat(".description")));
			entity.setStatus(Status.valueOf(Byte.valueOf(prop.getProperty(config.concat(".status"), "1"))));

			try {
				entity.setId(entityManageService.addEntity(entity));
			} catch (Exception e) {
				logger.warn("Init entity {} fail:{}", entity, e.getMessage());
			}

			String actionConfigs = prop.getProperty(config.concat(".actions"));

			if (!BlankUtils.isBlank(actionConfigs)) {
				initEntityPermissions(entity, actionConfigs, actionMap, permissionManageService);
			}
		}

		String entities = prop.getProperty(config.concat(".entities"));

		if (!BlankUtils.isBlank(entities)) {
			String[] childEntities = entities.split(",");
			for (String child : childEntities) {
				recursionInitEntity(child, entity, type, actionMap, prop, entityManageService, permissionManageService);
			}
		}
	}

	public void initEntityPermissions(Entity entity, String actions, Map<String, Action> actionMap, IPermissionManageService permissionManageService) {
		String[] actionsConfig = actions.split(",");

		for (String actionCode : actionsConfig) {
			Permission permission = new Permission();
			permission.setAction(actionMap.get(actionCode.toUpperCase()));
			permission.setEntity(entity);
			permission.setStatus(Status.ENABLED);
			permission.setCode(entity.getCode().concat(".").concat(actionCode));

			try {
				permissionManageService.addPermission(permission);
			} catch (ServiceException e) {
				logger.error("Init permission {} fail:{}", permission, e.getMessage());
			}
		}
	}
}
